#!/usr/bin/perl

#folders
$root_folder="/home/dongjin2/SVNROOT/ethernet-switch";
$result_folder="$root_folder/rinse_test/2_to_1/exp1"; #root dir to store experimental resutls
$aggregated_result="$result_folder/total_result.txt"; #results for all experiments, used for plot

$runs=1; # number of repeated experiment (same setting)
@mode=("linear", "voq");

#used to calculate gap (not used now)
$packet_size=1500; #byte

@speed;
#specify sending rate
$start_sending_rate=100;#Mb/s
$end_sending_rate=1000;
$sending_rate_gap=100;

$num_pkts = 10000;
#100Mb/s - 1000Mb/s, every 100Mb/s, slightly less than specified rate, according to real experiment
@flow1_send_rate=(-1,-1,-1,-1,-1,-1,-1,-1, 887.1e6,-1);
@flow2_send_rate=(99.081e6, 198.162e6, 295.875e6, 396.32e6, 495.404e6, 594.63e6, 691.28e6, 791.602e6, 887.624e6, 978e6);

print "@flow1_send_rate\n";
print "@flow2_send_rate\n";

for($i=0; $i<=$#flow1_send_rate; $i++)
{
	$flow1_send_interval[$i]=$packet_size*8.0/$flow1_send_rate[$i];
	$flow2_send_interval[$i]=$packet_size*8.0/$flow2_send_rate[$i];
}

print "@flow1_send_interval\n";
print "@flow2_send_interval\n";

#calculate speed and gap (gap is not used for now)
for($b=$start_sending_rate, $a=0; $b<=$end_sending_rate; $b+=$sending_rate_gap, $a++)
{
	$speed[$a]=$b;
	#print "\n speed = $speed[$a]\n";
}

open(OUT_RESULT, ">$aggregated_result") or die "$aggregated_result cannot be opened.\n";
print OUT_RESULT "flow1(Mb/s), flow2(Mb/s), switch_mode, loss_rate, lp_mean, lp_std, delay_mean(us), delay_std(us), jitter(us)\n";

#post-process data
#for($j=0; $j<=$#speed; $j++)
for($j=8; $j<=8; $j++)
{
	for($k=0; $k<=$#speed; $k++)
	#for($k=2; $k<=2; $k++)
	{
		#for($i=0; $i<=$#mode; $i++)
		for($i=0; $i<=0; $i++)
		{
			#chdir "$result_folder/$speed[$j]M/$speed[$k]M/$i";
			chdir "$result_folder/$speed[$j]M/$speed[$k]M/$mode[$i]";
			print "Processing $result_folder/$speed[$j]M/$speed[$k]M/$mode[$i]\n";		

			#compute end time
			if($flow1_send_interval[$j]<=$flow2_send_interval[$k])
			{
				$end_time = $num_pkts*$flow1_send_interval[$j];
			}
			else
			{
				$end_time = $num_pkts*$flow2_send_interval[$k];			
			}
			print "end time = $end_time\n";
			
			#run simulation
			system("make run");

			#extract delay/loss and sort according arrival_timestamp
			if($mode[$i] eq 'linear')
			{
				system("cat a.out \|grep \"haha\" >flow.csv");
			}
			elsif($mode[$i] eq 'voq')
			{
				system("cat a.out \|grep \"haha\" >flow_unsorted.csv");
				system("sort flow_unsorted.csv > flow.csv");
				system("rm -f flow_unsorted.csv");
			}

			#separate delay and loss_episode into two files
			$in_flow="flow.csv";
			$out_delay="delay.txt";
			$out_loss_episode="loss_episode.txt";

			open(IN_FLOW, $in_flow) or die "$in_flow cannot be opened.\n";
			open(OUT_DELAY, ">$out_delay") or die "$out_delay cannot be opened.\n";
			open(OUT_LP, ">$out_loss_episode") or die "$out_loss_episode cannot be opened.\n";

			
			$prev_delay=-1;
			$loss_counter=0;
			$successive_loss_counter=0;
			$total_counter=0;
			while($line=<IN_FLOW>)
			{				
				chomp($line);
				@line_block=split(', ', $line);
				$arrival_time=$line_block[0];
				$delay=$line_block[1];
				#$ip=$line_block[2];
	
				#print("$arrival_time, $delay\n");

				if($arrival_time>$end_time)
				{
					last;
				}
				
				if($delay!=0)
				{
					print OUT_DELAY "$delay\n";
				}
				if($delay==0)
				{
					$loss_counter=$loss_counter+1;
					$successive_loss_counter=$successive_loss_counter+1;						
				}				

				if($delay!=0 and $prev_delay==0)
				{
					print OUT_LP "$successive_loss_counter\n";
					$successive_loss_counter=0;
				}

				$prev_delay=$delay;
				$total_counter=$total_counter+1;

			}

			close(OUT_LP);
			close(OUT_DELAY);
			close(IN_FLOW);


			#compute delay mean/std/jitter
			$in_delay="delay.txt";
			open(INPUT_DELAY, $in_delay) or die "$in_delay cannot be opened.\n";
	
			$delay_counter = 0;
			$delay_sum = 0;
			$delay_square_sum = 0;
			$delay_mean = 0;
			$delay_var = 0;
			$delay_std = 0;
			$jitter_total = 0;
			$jitter = 0;

			$my_delay = <INPUT_DELAY>;
			chomp($my_delay);
			$delay_counter++;
			$delay_sum += $my_delay;
			$delay_square_sum += $my_delay**2;
			$prev_my_delay = $my_delay;

			while($my_delay = <INPUT_DELAY>)
			{			
				chomp($my_delay);			
				$delay_counter++;
				$delay_sum += $my_delay;
				$delay_square_sum += $my_delay**2;
				$jitter_total += abs($my_delay-$prev_my_delay);
			        $prev_my_delay = $my_delay;
			}

			$delay_mean = $delay_sum /$delay_counter;
			$delay_autocor = $delay_square_sum/$delay_counter;
			$delay_var = $delay_autocor-$delay_mean**2;
			$delay_std = sqrt($delay_var);
			$jitter = $jitter_total/($delay_counter-1);

			$delay_mean=$delay_mean*(10**6);
			$delay_std=$delay_std*(10**6);
			$jitter=$jitter*(10**6);

			$formatted_delay_mean=sprintf("%.3f", $delay_mean);
			$formatted_delay_std=sprintf("%.3f", $delay_std);
			$formatted_jitter=sprintf("%.3f", $jitter);
			close(INPUT_DELAY);
					
			#compute loss_episode mean and std
			$in_loss_episode="loss_episode.txt";
			open(INPUT_LP, $in_loss_episode) or die "$in_loss_episode cannot be opened.\n";
	
			$lp_counter = 0;
			$lp_sum = 0;
			$lp_square_sum = 0;
			$lp_mean = 0;
			$lp_var = 0;
			$lp_std = 0;

			while($my_lp = <INPUT_LP>)
			{			
				chomp($my_lp);			
				$lp_counter++;
				$lp_sum += $my_lp;
				$lp_square_sum += $my_lp**2;
			}

			$lp_mean = $lp_sum /$lp_counter;
			$lp_autocor = $lp_square_sum/$lp_counter;
			$lp_var = $lp_autocor-$lp_mean**2;
			$lp_std = sqrt($lp_var);

			$formatted_lp_mean=sprintf("%.3f", $lp_mean);
			$formatted_lp_std=sprintf("%.3f", $lp_std);
			close(INPUT_IP);
			
			#output result
			#flow1_sending_rate, flow2_sending_rate, switch_mode, avg_loss_rate, loss_episode_mean, loss_episode_std, delay_mean, delay_std, jitter
			#print "loss = $loss_counter, total = $total_counter\n";

			$loss_rate=$loss_counter*1.0/$total_counter;
			$formatted_loss_rate=sprintf("%.3f", $loss_rate);
			print OUT_RESULT "$speed[$j] $speed[$k] $mode[$i] $formatted_loss_rate $formatted_lp_mean $formatted_lp_std $formatted_delay_mean $formatted_delay_std $formatted_jitter\n";

#clean up

			
		}
	}
}

close(OUT_RESULT);

chdir "$root_folder/script/rinse_test";
